/**
*	@class Vector4
*
*	@brief This class implements a 4D Vector object.
*
*	@author William McVicar
*/

#pragma once

#ifndef __VECTOR4_BASIC_H_INCLUDED__
#define __VECTOR4_BASIC_H_INCLUDED__

#ifndef PROTEIN_USE_SIMD

#pragma warning( disable : 4324 )
#pragma warning( disable : 4201 )

// Library Includes

// Local Includes
#include "MathCommon.h"

// Types

// Constants

// Prototypes

namespace Protein
{

template <class Real>
class Vector4
{

public:

  Vector4();
	Vector4( Real x, Real y, Real z );
	Vector4( Real val );
	Vector4( const Vector4& other );
	Vector4( Real* in );
	~Vector4();

  void                    set( Real x, Real y, Real z );
  void                    set( Real val );

  Vector4&                operator=( const Vector4& rhs );

	Vector4	                operator+( const Vector4& rhs ) const;
	Vector4	                operator-( const Vector4& rhs ) const;
	Vector4	                operator*( Real rhs ) const;
	Vector4	                operator/( Real rhs ) const;
	Vector4	                operator-() const;

	Vector4&	              operator+=( const Vector4& rhs );
	Vector4&	              operator-=( const Vector4& rhs );
	Vector4&	              operator*=( Real rhs );
	Vector4&	              operator/=( Real rhs );

	bool			              operator==( const Vector4& rhs ) const;
	bool			              operator!=( const Vector4& rhs ) const;
	bool			              operator> ( const Vector4& rhs ) const;
	bool			              operator< ( const Vector4& rhs ) const;
	bool			              operator>=( const Vector4& rhs ) const;
	bool			              operator<=( const Vector4& rhs ) const;

	Real			              dot( const Vector4& in ) const;
	Vector4		              cross( const Vector4& in ) const;
  Vector4                 unitCross( const Vector4& in ) const;
	Real			              length() const;
	Real			              lengthSqr() const;

	void			              normalise();
	Vector4			            normalised() const;

	Real			              distance( const Vector4& in ) const;
	Real			              distanceSqr( const Vector4& in ) const;

	static Real	            dot( const Vector4& a, const Vector4& b );
	static Vector4	        cross( const Vector4& a, const Vector4& b );
  static Vector4          unitCross( const Vector4& a, const Vector4& b );
	static Real	            length( const Vector4& in );
	static Real	            lengthSqr( const Vector4& in );
	static Real	            distance( const Vector4& a, const Vector4& b );
	static Real	            distanceSqr( const Vector4& a, const Vector4& b );

	static const Vector4    Zero;  
	static const Vector4    i;	    
	static const Vector4    j;	    
	static const Vector4    k;	    
	static const Vector4    negi;	
	static const Vector4    negj;	
	static const Vector4    negk;

  union
	{
		struct
    { 
      Real x;
      Real y;
      Real z;
      Real w;
    };

	  Real m_components[4];
  };
};

template < class Real >
Vector4<Real> operator*( Real val, const Vector4<Real>& in );

#include "Vector4_Basic.inl"

typedef Vector4<f32> Vector4f;
typedef Vector4<f64> Vector4d;

}

#pragma warning( default : 4201 )
#pragma warning( default : 4324 )

#endif // PROTEIN_USE_SIMD
#endif // __VECTOR3_H_